//Page 435
//All the containers in STL hold copies of objects you place in
//them, so your objects must be copy-constructible and assignable.
//Usually, you'd like to store pointers to these objects, so that 
//you can take advantage of polymorphic.

#include <vector>
#include <list>
#include <iostream>
#include <iterator>

using namespace std ;

class Shape
{
public:
	virtual void draw ( ) = 0 ;
	virtual ~Shape ( ) { }
};

class Circle : public Shape
{
public:
	virtual void draw ( ) { cout << "Circle::draw" << endl ; }
	virtual ~Circle( ) { cout<< "~Circle" << endl ; }
};

class Triangle : public Shape
{
public:
	virtual void draw ( ) { cout << "Triangle::draw" << endl ; }
	virtual ~Triangle( ) { cout<< "~Triangle" << endl ; }
};

class Square : public Shape
{
public:
	virtual void draw ( ) { cout << "Square::draw" << endl ; }
	virtual ~Square( ) { cout<< "~Square" << endl ; }
};

template<typename T>
class FreeRes
{
public:
	T * operator() (T * pT)
	{
		delete pT;
		return NULL ;
	}
} ;

int main ( )
{
	typedef std::list<Shape *> Container ; //NoteA. OK to use "typedef std::vector<Shape *> Container ;" with NoteB.
	Container Con ;
	Con.push_back ( new Circle ) ;
	Con.push_back ( new Triangle) ;
	Con.push_back ( new Square ) ;
	Con.push_back ( new Circle ) ;
	
	std::list<Shape *>::iterator iter ; //NoteB. OK to use "std::list<Shape *>::iterator iter ;" with NoteA.

	//"iter < Con.end()" is only valid for vector. For other container,
	//such as list, != is valid. "!=" is recommended for all containers.
	//Con.end() returns one past the end of sequence.
	for ( iter=Con.begin(); iter != Con.end(); iter++ )
		(*iter)->draw() ;

	transform(Con.begin(), Con.end(), Con.begin(), FreeRes<Shape>());
	
	copy(Con.begin(), Con.end(), ostream_iterator<Shape *>(cout, "\t")) ;
	cout<< endl ;

	return 0 ;
}
